package com.ybzl.gateway.netty;

import com.alibaba.fastjson.JSONObject;
import com.ybzl.gateway.config.StationConfig;
import com.ybzl.gateway.netty.decoder.YbzlDecoder;
import com.ybzl.gateway.netty.handler.DataHandler;
import com.ybzl.gateway.service.IDeviceService;
import com.ybzl.gateway.utils.SlidingWindowProcessor;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.util.concurrent.ThreadPoolExecutor;

@Component
public class NettyServer {

    @Autowired
    private IDeviceService deviceService;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StationConfig config;

    @Autowired
    private SlidingWindowProcessor processor;

    private static final Logger log = LoggerFactory.getLogger(NettyServer.class);

    @Value("${rssi}")
    private Integer rssi;


    public void start(InetSocketAddress address) {
        //配置服务端的NIO线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup(20);

        try {
            ServerBootstrap bootstrap = new ServerBootstrap()
                    .group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .localAddress(address)
                    .option(ChannelOption.SO_BACKLOG, 150)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)

                    /**
                     *  DataHandler 在同一线程上是共享的。
                     *  【需要考虑同一个业务线程处理并发任务时的数据一致性问题】
                     * 2025-10-18 12:57:53,574|[nioEventLoopGroup-5-3]|INFO |com.ybzl.gateway.netty.handler.DataHandler|61|-channelRead0 is：com.ybzl.gateway.netty.handler.DataHandler@57de0c08
                     * 2025-10-18 12:57:53,621|[nioEventLoopGroup-5-3]|INFO |com.ybzl.gateway.netty.handler.DataHandler|61|-channelRead0 is：com.ybzl.gateway.netty.handler.DataHandler@57de0c08
                     */
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
                            ch.pipeline().addLast(new YbzlDecoder());
                            ch.pipeline().addLast(new DataHandler(deviceService, threadPoolExecutor
                                    , redisTemplate, processor, config));
                            // , redisTemplate, new SlidingWindowProcessor(3000, 3000, redisTemplate, rssi),config));
                        }
                    });

            // 绑定端口，开始接收进来的连接
            ChannelFuture future = bootstrap.bind(address).sync();
            log.info("netty服务器开始监听端口：" + address.getPort());
            //关闭channel和块，直到它被关闭
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
